package com.xbts.system.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaweicloud.sdk.bss.v2.model.*;
import com.huaweicloud.sdk.core.utils.JsonUtils;
import com.huaweicloud.sdk.ecs.v2.model.*;
import com.huaweicloud.sdk.ecs.v2.model.ShowJobResponse;
import com.huaweicloud.sdk.ecs.v2.model.SubJob;
import com.huaweicloud.sdk.eip.v2.model.ListPublicipsRequest;
import com.huaweicloud.sdk.eip.v2.model.ListPublicipsResponse;
import com.huaweicloud.sdk.eip.v2.model.PublicipShowResp;
import com.huaweicloud.sdk.eip.v2.model.UpdatePrePaidBandwidthRequest;
import com.huaweicloud.sdk.evs.v2.model.*;
import com.xbts.common.core.domain.AjaxResult;
import com.xbts.common.core.domain.entity.SysUser;
import com.xbts.common.core.redis.RedisDelayQueueUtil;
import com.xbts.common.enums.*;
import com.xbts.common.exception.ServiceException;
import com.xbts.common.utils.DateUtils;
import com.xbts.common.utils.SecurityUtils;
import com.xbts.common.utils.SnowFlakeUtil;
import com.xbts.common.utils.StringUtils;
import com.xbts.common.utils.bean.BeanUtils;
import com.xbts.system.domain.CnOrder;
import com.xbts.system.domain.CnOrderItem;
import com.xbts.system.domain.CnUserCloudServersRelation;
import com.xbts.system.domain.SysMessage;
import com.xbts.system.domain.dto.*;
import com.xbts.system.enums.OrderStatusEnum;
import com.xbts.system.enums.OrderTypeEnum;
import com.xbts.system.mapper.CnOrderMapper;
import com.xbts.system.module.payment.enums.PaymentMethodEnum;
import com.xbts.system.module.payment.service.ICnWalletLogService;
import com.xbts.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author xbts
 * @date 2023-08-03
 */
@Service
@Slf4j
public class CnOrderServiceImpl extends ServiceImpl<CnOrderMapper, CnOrder> implements ICnOrderService {

    @Autowired
    private ICloudServiceService cloudServiceService;
    @Autowired
    private ICloudControlService cloudControlService;

    @Autowired
    private ICnOrderItemService cnOrderItemService;
    @Autowired
    private ICnOrderService cnOrderService;

    @Autowired
    private ICnUserCloudServersRelationService userCloudServersRelationService;

    @Autowired
    private ISysUserService userService;
    @Autowired
    private ICnWalletLogService cnWalletLogService;
    @Autowired
    private EmailSendService emailSendService;
    @Autowired
    private ISysMessageService sysMessageService;
    @Autowired
    private ICnWeChatTemplateMsgService cnWeChatTemplateMsgService;
    @Autowired
    private RedisDelayQueueUtil redisDelayQueueUtil;
    @Autowired
    private ISmsService smsService;

    /**
     * 查询订单列表
     *
     * @param cnOrder 订单
     * @return 订单
     */
    @Override
    public List<CnOrder> selectCnOrderList(CnOrder cnOrder) {
        QueryWrapper<CnOrder> queryWrapper = cnOrder.queryWrapper();
        return list(queryWrapper);
    }

    /**
     * 查询订单
     *
     * @param orderId 订单主键
     * @return 订单
     */
    @Override
    public CnOrder selectCnOrderByOrderId(String orderId) {
        return getById(orderId);
    }

    /**
     * 新增订单
     *
     * @param cnOrder 订单
     * @return 结果
     */
    @Override
    public boolean insertCnOrder(CnOrder cnOrder) {
        cnOrder.setCreateBy(SecurityUtils.getUserId().toString());
        return save(cnOrder);
    }

    /**
     * 修改订单
     *
     * @param cnOrder 订单
     * @return 结果
     */
    @Override
    public boolean updateCnOrder(CnOrder cnOrder) {
        cnOrder.setUpdateBy(SecurityUtils.getUserId().toString());
        cnOrder.setUpdateTime(DateUtils.getNowDate());
        return updateById(cnOrder);
    }

    /**
     * 批量删除订单
     *
     * @param orderIds 需要删除的订单主键
     * @return 结果
     */
    @Override
    public boolean deleteCnOrderByOrderIds(List<String> orderIds) {
        return removeBatchByIds(orderIds);
    }

    /**
     * 删除订单信息
     *
     * @param orderId 订单主键
     * @return 结果
     */
    @Transactional
    @Override
    public boolean deleteCnOrderByOrderId(String orderId) {
        return removeById(orderId);
    }

    /**
     * 审核
     *
     * @param cnOrderItem 子订单
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult review(CnOrderItem cnOrderItem) {

        if (StringUtils.isNull(cnOrderItem.getOrderStatus())) {
            return AjaxResult.error("审核状态不能为空");
        }
        CnOrderItem dbCnOrderItem = cnOrderItemService.getById(cnOrderItem.getOrderItemId()); // 从数据库中取出订单
        CnOrder dbCnOrder = getById(dbCnOrderItem.getOrderId()); // 从数据库中取出订单
        if (!dbCnOrderItem.getOrderStatus().equals(OrderStatusEnum.IN_PROGRESS)) {
            return AjaxResult.error("订单已审核，请勿重复审核");
        }
        SysUser sysUser = userService.selectUserById(dbCnOrderItem.getUserId());
        cnOrderItem.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        cnOrderItem.setInvoicing("0"); // 待开发票
        cnOrderItem.setContractStatus("0"); // 待开合同票
        cnOrderItemService.updateById(cnOrderItem);
        // 修改子订单合同状态和发票状态
//        BeanUtils.copyBeanProp(cnOrderItem, dbCnOrderItem);
//        if (dbCnOrder.getPaymentMethod().equals(PaymentMethodEnum.ACCOUNT.name())) {
//            companyPay(dbCnOrderItem, dbCnOrder);
//        } else {
        boolean isSkip = false;// 是否跳过

        String title = "";
        String content = "";
        // 创建站内信消息
        SysMessage sysMessage = new SysMessage();
        sysMessage.setIsAll(1);
        sysMessage.setUserIds(Collections.singletonList(dbCnOrderItem.getUserId()));
        sysMessage.setNoticeType(2);

        if (cnOrderItem.getOrderStatus().equals(OrderStatusEnum.SUCCESS)) {

            isSkip = dbCnOrderItem.getShoppingCarType().equals(OrderTypeEnum.SYSTEM.name()); // 是否跳过

            // 创建华为云服务器-------云市场和政务云不用创建服务器
            if (dbCnOrderItem.getShoppingCarEnums().equals(ShoppingCarEnums.CLOUD_SERVER) && !isSkip) {
                // 购买服务器
                queryAndSaveServerStatus(dbCnOrder.getPaymentMethod(), dbCnOrderItem);
            } else if (dbCnOrderItem.getShoppingCarEnums().equals(ShoppingCarEnums.CLOUD_SERVER) && isSkip) {
                Long cnUserCloudServersRelationId = dbCnOrderItem.getCnUserCloudServersRelationId();
                CnUserCloudServersRelation cloudServersRelation = userCloudServersRelationService.getById(cnUserCloudServersRelationId);

                // 云服务器，自动续费
                List<String> resourceIds = new ArrayList<>();
                resourceIds.add(cloudServersRelation.getRelationId());
                RenewalResourcesReqDTO dto = new RenewalResourcesReqDTO();
                dto.setResourceIds(resourceIds);
                dto.setPeriodNum(1);
                dto.setPeriodType(dbCnOrderItem.getPeriodType() > 30 ? 3 : 2);
                dto.setExpirePolicy(0);
                dto.setIsAutoPay(1);
                AjaxResult ajaxResult = cloudControlService.renewalResources(dto);
                log.info("服务器续费结果：" + ajaxResult);
                Integer code = (Integer) ajaxResult.get("code");
                if (code != 200) {
                    throw new ServiceException("服务器续费失败！");
                } else {
                    Integer count = 0;
                    // 更新用户总共购买月份
                    if (dto.getPeriodType() == 2) {
                        count += 1;
                    } else {
                        count += 12;
                    }
                    Integer months = cloudServersRelation.getMonths();
                    cloudServersRelation.setMonths(months + count);
                    cloudServersRelation.setEbsPrice(cloudServersRelation.getEbsPrice().add(dbCnOrderItem.getEbsPrice()));
                    cloudServersRelation.setVpcPrice(cloudServersRelation.getVpcPrice().add(dbCnOrderItem.getVpcPrice()));
                    cloudServersRelation.setEc2Price(cloudServersRelation.getEc2Price().add(dbCnOrderItem.getEc2Price()));

                    userCloudServersRelationService.updateById(cloudServersRelation);
                }
            } else if (dbCnOrderItem.getShoppingCarEnums().equals(ShoppingCarEnums.CLOUD_MARKET) || dbCnOrderItem.getShoppingCarEnums().equals(ShoppingCarEnums.GOV_CLOUD)) {
                if (isSkip) {
                    // 系统自动续费订单
                    // 发送短信
                    String msg = String.format("服务器ID为【%s】自动续费成功", cnOrderItem.getRelationId());
                    SmsDTO smsDTO = new SmsDTO(msg, sysUser.getPhonenumber());
                    smsService.sendMsg(smsDTO, SmsTemplateEnum.EXPIRATION_NOTICE);
                    log.info("自动续费msg = {}", msg);
                    //更新用户关系表
                    Long cnUserCloudServersRelationId = dbCnOrderItem.getCnUserCloudServersRelationId();
                    CnUserCloudServersRelation cnUserCloudServersRelation = userCloudServersRelationService.getById(cnUserCloudServersRelationId);
                    Date expirationTime = DateUtils.calcExpirationTime(dbCnOrderItem.getPeriodType(), dbCnOrderItem.getPeriodNum(), cnUserCloudServersRelation.getExpirationTime());
                    // 更新到期时间
                    cnUserCloudServersRelation.setExpirationTime(expirationTime);
                    cnUserCloudServersRelation.setBuyingTime(new Date());
                    userCloudServersRelationService.updateById(cnUserCloudServersRelation);
                } else { // 用户购买订单
                    saveUserAndServerRelation(dbCnOrderItem, dbCnOrder.getSn());
                }
            } else if (dbCnOrderItem.getShoppingCarEnums().equals(ShoppingCarEnums.CLOUD_SERVER_CHANGE)) {
                // 服务器变更
                ResizeServerRequestDTO resizeServerRequestDTO = new ResizeServerRequestDTO();
                String jsonStr = dbCnOrderItem.getJsonStr();
                JSONObject jsonObject = JSONObject.parseObject(jsonStr);
                String id = jsonObject.getString("id");
                CnUserCloudServersRelation cloudServersRelation = userCloudServersRelationService.getById(id);
                String relationId = cloudServersRelation.getRelationId();
                Integer type = jsonObject.getInteger("type");
                if (type == 1) {
                    String flavorRef = jsonObject.getString("flavorRef");
                    // 执行服务器变更
                    resizeServerRequestDTO.setServerId(relationId);
                    ResizeServerRequestBody body = new ResizeServerRequestBody();
                    ResizePrePaidServerOption resize = new ResizePrePaidServerOption();
                    resize.setFlavorRef(flavorRef);
                    // 支持开机状态变更规格
                    resize.setMode("withStopServer");
                    // 自动支付
                    ResizeServerExtendParam resizeServerExtendParam = new ResizeServerExtendParam();
                    resizeServerExtendParam.setIsAutoPay("true");
                    resize.setExtendparam(resizeServerExtendParam);
                    body.setResize(resize);
                    resizeServerRequestDTO.setBody(body);
                    AjaxResult ajaxResult = cloudServiceService.resizeServer(resizeServerRequestDTO);
                    log.info("执行服务器变更结果：{}", ajaxResult);
                    Integer code = (Integer) ajaxResult.get("code");
                    ResizeServerResponse response = (ResizeServerResponse) ajaxResult.get("data");
                    if (code != 200) {
                        throw new ServiceException("执行服务器变更失败！");
                    } else {
                        long startTime = System.currentTimeMillis();
                        String orderItemId = cnOrderItem.getOrderItemId();
                        // 异步线程查询服务器创建状态
                        ThreadUtil.execAsync(() -> {

                            ShowJobResponse.StatusEnum statusEnum = ShowJobResponse.StatusEnum.RUNNING;
                            CnOrderItem orderItem = cnOrderItemService.getById(orderItemId);
                            try {
                                // 执行10分钟
                                while ((System.currentTimeMillis() - startTime) < 1000 * 60 * 10) {
                                    ShowJobResponse showJobResponse = cloudServiceService.showJob(response.getJobId(), orderItem.getRegionId());
                                    if (null == showJobResponse) return;
                                    statusEnum = showJobResponse.getStatus();
                                    log.debug("执行服务器变更: " + showJobResponse.getStatus());
                                    if (showJobResponse.getStatus().equals(ShowJobResponse.StatusEnum.SUCCESS)) {
                                        // 修改服务器规格实际花费，和总花费
                                        BigDecimal ec2Price = cloudServersRelation.getEc2Price();
                                        BigDecimal updatePrice = cloudServersRelation.getUpdatePrice();
                                        cloudServersRelation.setEc2Price(ec2Price.add(dbCnOrderItem.getEc2Price()));
                                        cloudServersRelation.setUpdatePrice(updatePrice.add(dbCnOrderItem.getEc2Price()));

                                        // 修改服务器续费查价字符串
                                        updatePriceQueryJsonStr(cloudServersRelation, orderItem);
                                        userCloudServersRelationService.updateById(cloudServersRelation);
                                        break;
                                    } else if (showJobResponse.getStatus().equals(ShowJobResponse.StatusEnum.FAIL)) {
                                        taskFailed(response.getJobId(), orderItem, showJobResponse);
                                        break;
                                    }
                                    Thread.sleep(1000 * 10);
                                }

                            } catch (Exception e) {
                                log.error("异步服务器变更失败" + e);
                            }
                            if (!statusEnum.equals(ShowJobResponse.StatusEnum.SUCCESS)) {
                                taskFailed(response.getJobId(), orderItem, null);
                            }
                            log.debug("异步服务器变更状态结束");
                        });

                    }
                } else if (type == 2) {
                    JSONArray disks = jsonObject.getJSONArray("disks");
                    for (int i = 0; i < disks.size(); i++) {
                        // 获取新增磁盘数组
                        JSONObject disk = disks.getJSONObject(i);
                        // 新增磁盘
                        RegionIdDTO<CreateVolumeRequest> regionIdDTO = new RegionIdDTO<>();
                        CreateVolumeRequest request = new CreateVolumeRequest();
                        regionIdDTO.setBody(request);
                        CreateVolumeRequestBody body = new CreateVolumeRequestBody();
                        request.setBody(body);
                        BssParamForCreateVolume bssParam = new BssParamForCreateVolume();
                        bssParam.setChargingMode(BssParamForCreateVolume.ChargingModeEnum.PREPAID);
                        body.setBssParam(bssParam);
                        body.setServerId(relationId);

                        CreateVolumeOption volume = new CreateVolumeOption();
                        volume.setVolumeType(CreateVolumeOption.VolumeTypeEnum.valueOf(disk.getString("diskType")));
                        volume.setSize(disk.getInteger("size"));

                        // 查询服务器信息，获取服务器可用区
                        RegionIdDTO<ShowServerRequest> ShowServerRequesRegionIdDTO = new RegionIdDTO<>();
                        ShowServerRequesRegionIdDTO.setRegionId(relationId);
                        // 发送请求
                        ShowServerResponse showServerResponse = cloudControlService.showServer(ShowServerRequesRegionIdDTO);
                        if (StringUtils.isNull(showServerResponse)) {
                            throw new ServiceException("查询服务器信息失败！");
                        }
                        // 获取可用区
                        ServerDetail server = showServerResponse.getServer();
                        String osEXTAZAvailabilityZone = server.getOsEXTAZAvailabilityZone();

                        volume.setAvailabilityZone(osEXTAZAvailabilityZone);
                        body.setVolume(volume);
                        CreateVolumeResponse response = cloudControlService.createVolume(regionIdDTO);

                        long startTime = System.currentTimeMillis();
                        String orderItemId = cnOrderItem.getOrderItemId();
                        // 异步线程查询服务器创建状态
                        ThreadUtil.execAsync(() -> {

                            CnOrderItem orderItem = cnOrderItemService.getById(orderItemId);
                            ShowJobResponse.StatusEnum statusEnum = ShowJobResponse.StatusEnum.RUNNING;
                            try {
                                // 执行10分钟
                                while ((System.currentTimeMillis() - startTime) < 1000 * 60 * 10) {
                                    ShowJobResponse showJobResponse = cloudServiceService.showJob(response.getJobId(), orderItem.getRegionId());
                                    if (null == showJobResponse) return;
                                    log.debug("正在创建硬盘: " + showJobResponse.getStatus());
                                    statusEnum = showJobResponse.getStatus();
                                    if (showJobResponse.getStatus().equals(ShowJobResponse.StatusEnum.SUCCESS)) {
                                        // 服务器新增磁盘成功
                                        // 更新磁盘实际价格
                                        BigDecimal ebsPrice = cloudServersRelation.getEbsPrice();
                                        BigDecimal updatePrice = cloudServersRelation.getUpdatePrice();
                                        cloudServersRelation.setEbsPrice(ebsPrice.add(orderItem.getEbsPrice()));
                                        cloudServersRelation.setUpdatePrice(updatePrice.add(orderItem.getEbsPrice()));

                                        // 修改服务器续费查价字符串
                                        updatePriceQueryJsonStr(cloudServersRelation, orderItem);
                                        userCloudServersRelationService.updateById(cloudServersRelation);
                                        break;
                                    } else if (showJobResponse.getStatus().equals(ShowJobResponse.StatusEnum.FAIL)) {
                                        taskFailed(response.getJobId(), orderItem, showJobResponse);
                                        break;
                                    }
                                    Thread.sleep(1000 * 10);
                                }
                            } catch (Exception e) {
                                log.error("异步查询创建硬盘失败" + e);
                            }
                            if (!statusEnum.equals(ShowJobResponse.StatusEnum.SUCCESS)) {
                                taskFailed(response.getJobId(), orderItem, null);
                            }
                            log.debug("异步创建硬盘结束");
                        });
                    }

                } else if (type == 3) {
                    String ip = "";
                    // 查询服务器信息，获取公网IP
                    RegionIdDTO<ShowServerRequest> regionIdDTO = new RegionIdDTO<>();
                    regionIdDTO.setRegionId(relationId);
                    ShowServerResponse showServerResponse = cloudControlService.showServer(regionIdDTO);
                    if (StringUtils.isNull(showServerResponse)) {
                        throw new ServiceException("查询服务器信息失败！");
                    }
                    Map<String, List<ServerAddress>> addresses = showServerResponse.getServer().getAddresses();
                    Collection<List<ServerAddress>> values = addresses.values();
                    for (List<ServerAddress> value : values) {
                        for (ServerAddress serverAddress : value) {
                            if (serverAddress.getOsEXTIPSType().equals(ServerAddress.OsEXTIPSTypeEnum.FLOATING)) {
                                ip = serverAddress.getAddr();
                            }
                        }
                    }
                    if (StringUtils.isBlank(ip)) {
                        throw new ServiceException("查询服务器公网IP失败！");
                    }
                    // 修改带宽
                    RegionIdDTO<UpdatePrePaidBandwidthRequest> updatePrePaidBandwidthDTO = new RegionIdDTO<>();
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("publicIp", ip);
                    updatePrePaidBandwidthDTO.setParams(map);
                    AjaxResult ajaxResult = cloudControlService.updatePrePaidBandwidth(updatePrePaidBandwidthDTO);
                    log.info("修改带宽结果：" + ajaxResult);
                    Integer code = (Integer) ajaxResult.get("code");
                    if (code != 200) {
                        throw new ServiceException("修改带宽失败！");
                    } else {
                        // 更新宽带实际花费和总花费
                        BigDecimal vpcPrice = cloudServersRelation.getVpcPrice();
                        BigDecimal updatePrice = cloudServersRelation.getUpdatePrice();
                        cloudServersRelation.setVpcPrice(vpcPrice.add(dbCnOrderItem.getVpcPrice()));
                        cloudServersRelation.setUpdatePrice(updatePrice.add(dbCnOrderItem.getVpcPrice()));

                        // 修改服务器续费查价字符串
                        updatePriceQueryJsonStr(cloudServersRelation, dbCnOrderItem);
                        userCloudServersRelationService.updateById(cloudServersRelation);
                    }
                }
                // 服务器变更后更新服务器配置信息
                redisDelayQueueUtil.addDelayQueue(cloudServersRelation.getId().toString(), 11, TimeUnit.MINUTES, RedisDelayQueueEnum.UPDATE_CLOUD_SERVICE_JSON_STR.getCode());
            } else if (dbCnOrderItem.getShoppingCarEnums().equals(ShoppingCarEnums.CLOUD_SERVER_RENEW)) {
                // 服务器续费
                String jsonStr = dbCnOrderItem.getJsonStr();
                JSONObject jsonObject = JSONObject.parseObject(jsonStr);
                String id = jsonObject.getString("id");
                Integer periodNum = jsonObject.getInteger("period_num");
                Integer periodType = jsonObject.getInteger("period_type");
                CnUserCloudServersRelation cloudServersRelation = userCloudServersRelationService.getById(id);


                // 服务器ID
                List<String> resourceIds = new ArrayList<>();
                resourceIds.add(cloudServersRelation.getRelationId());
                // 获取弹性公网ID
                String serversJsonStr = cloudServersRelation.getJsonStr();
                ListServersDetailsResponse response = JsonUtils.toObject(serversJsonStr, ListServersDetailsResponse.class);
                if (response != null) {
                    List<ServerDetail> servers = response.getServers();
                    if (servers != null && servers.size() > 0) {
                        ServerDetail serverDetail = servers.get(0);
                        // 获取服务器ip
                        Map<String, List<ServerAddress>> addresses = serverDetail.getAddresses();
                        List<ServerAddress> collect = addresses.values().stream().flatMap(List::stream).collect(Collectors.toList());
                        List<ServerAddress> addressList = collect.stream()
                                .filter(serverAddress -> ServerAddress.OsEXTIPSTypeEnum.FLOATING.equals(serverAddress.getOsEXTIPSType())).collect(Collectors.toList());
                        String addr = addressList.get(0).getAddr();

                        RegionIdDTO<ListPublicipsRequest> listPublicipsRequestRegionIdDTO = new RegionIdDTO<>();
                        listPublicipsRequestRegionIdDTO.setRegionId(cloudServersRelation.getRegionId());
                        ListPublicipsRequest request = new ListPublicipsRequest();
                        listPublicipsRequestRegionIdDTO.setBody(request);
                        ListPublicipsResponse listPublicipsResponse = cloudControlService.listPublicips(listPublicipsRequestRegionIdDTO);
                        List<PublicipShowResp> publicips = listPublicipsResponse.getPublicips();
                        for (PublicipShowResp publicip : publicips) {
                            String publicIpAddress = publicip.getPublicIpAddress();
                            if (publicIpAddress.equals(addr)) {
                                resourceIds.add(publicip.getId());
                            }
                        }
                    }
                }
                RenewalResourcesReqDTO dto = new RenewalResourcesReqDTO();
                dto.setResourceIds(resourceIds);
                dto.setPeriodNum(periodNum);
                dto.setPeriodType(periodType);
                dto.setExpirePolicy(0);
                dto.setIsAutoPay(1);
                AjaxResult ajaxResult = cloudControlService.renewalResources(dto);
                log.info("服务器续费结果：" + ajaxResult);
                Integer code = (Integer) ajaxResult.get("code");
                if (code != 200) {
                    String str = (String) ajaxResult.get(AjaxResult.MSG_TAG);
                    throw new ServiceException("服务器续费失败！" + str);
                } else {
                    Integer count = 0;
                    // 更新用户总共购买月份
                    if (periodType == 2) {
                        count += periodNum;
                    } else if (periodType == 3) {
                        count += 12 * periodNum;
                    }
                    Integer months = cloudServersRelation.getMonths();
                    cloudServersRelation.setMonths(months + count);
                    cloudServersRelation.setMonths(months + count);
                    cloudServersRelation.setEbsPrice(cloudServersRelation.getEbsPrice().add(dbCnOrderItem.getEbsPrice()));
                    cloudServersRelation.setVpcPrice(cloudServersRelation.getVpcPrice().add(dbCnOrderItem.getVpcPrice()));
                    cloudServersRelation.setEc2Price(cloudServersRelation.getEc2Price().add(dbCnOrderItem.getEc2Price()));
                    userCloudServersRelationService.updateById(cloudServersRelation);
                }
            }

            // 修改订单状态和发票状态，合同状态为“待开发票”
            CnOrder updateCnOrder = new CnOrder();
            updateCnOrder.setOrderId(dbCnOrder.getOrderId());
            updateCnOrder.setOrderStatus(OrderStatusEnum.SUCCESS);
            updateCnOrder.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
            cnOrderService.updateById(updateCnOrder);

            content = "您购买的: " + dbCnOrderItem.getOrderAbstract() + " 审核成功";
            title = "订单审核成功";
            cnOrderItemService.updateById(cnOrderItem);

            // 对公账户支付的需要保存流水
            if (dbCnOrder.getPaymentMethod().equals(PaymentMethodEnum.ACCOUNT.name())) {
                // 扣减余额
                cnWalletLogService.updateUserBalanceAndLog(dbCnOrder.getUserId(),
                        dbCnOrderItem.getUpdatePrice().negate(), PaymentMethodEnum.ACCOUNT.name(), null, dbCnOrderItem.getShoppingCarEnums(), dbCnOrderItem.getSn(), null);
            }

        } else {
            // 修改订单状态
            CnOrder updateCnOrder = new CnOrder();
            updateCnOrder.setOrderId(dbCnOrderItem.getOrderId());
            updateCnOrder.setOrderStatus(OrderStatusEnum.FAIL);
            cnOrderService.updateById(updateCnOrder);
            // 修改子订单合同状态和发票状态
            LambdaUpdateWrapper<CnOrderItem> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(CnOrderItem::getOrderItemId, cnOrderItem.getOrderItemId())
                    .set(CnOrderItem::getOrderStatus, OrderStatusEnum.FAIL);
            cnOrderItemService.update(updateWrapper);

            // 系统自动生成的订单是先审核后扣款，所以不需要退款
            if (dbCnOrder.getShoppingCarType().equals(OrderTypeEnum.SYSTEM.name())) {
                ShoppingCarEnums shoppingCarEnums = dbCnOrderItem.getShoppingCarEnums();// 获取购物车类型，续费的订单只会有一个子订单
                // 云市场和政务云不用取消自动续费，华为云服务器需要取消自动续费
                if (shoppingCarEnums.equals(ShoppingCarEnums.CLOUD_SERVER)) {
                    // 取消自动续费
                    CancelAutoRenewalResourcesRequest cancelAutoRenewalResourcesRequest = new CancelAutoRenewalResourcesRequest();
                    cancelAutoRenewalResourcesRequest.setResourceId(dbCnOrderItem.getRelationId());
                    cloudServiceService.cancelAutoRenewalResources(cancelAutoRenewalResourcesRequest);
                }
            } else {
                // 对公账户支付的不需要退款
                if (!dbCnOrder.getPaymentMethod().equals(PaymentMethodEnum.ACCOUNT.name())) {
                    // 修改用户余额
                    cnWalletLogService.updateUserBalanceAndLog(dbCnOrderItem.getUserId(),
                            dbCnOrderItem.getUpdatePrice(),
                            PaymentMethodEnum.REFUND.name(), null, dbCnOrderItem.getShoppingCarEnums(), dbCnOrder.getSn(), null);
                }
                // 审核不通过,发送短信
                String msg = String.format("[\"%s\",\"%s\"]", dbCnOrderItem.getShoppingCarEnums().getDescription(), dbCnOrder.getSn());
                SmsDTO smsDTO = new SmsDTO(msg, sysUser.getPhonenumber());
                smsService.sendMsg(smsDTO, SmsTemplateEnum.EXPIRATION_NOTICE);
            }
            content = "您购买的: " + dbCnOrderItem.getOrderAbstract() + " 审核失败";
            title = "订单审核失败";
        }
        sysMessage.setNoticeContent(content);
        sysMessage.setNoticeTitle(title);
        sysMessageService.addSysMessage(sysMessage);

        // 发送邮件
        //获取用户邮箱地址
        String email = userService.getEmailByUserId(cnOrderItem.getUserId());
        emailSendService.sendMessage(new EmailSendDTO(email, title, EmailTypeEnum.ORDER_REVIEW, dbCnOrderItem.getOrderAbstract(),DateUtils.getTime()));

        CnOrderItem orderItem = cnOrderItemService.getById(cnOrderItem.getOrderItemId());
        cnWeChatTemplateMsgService.sendOrderReviewResultNotificationMsg(orderItem.getUserId().toString(), orderItem);
//        }
        return AjaxResult.success();
    }

    private void taskFailed(String jobId, CnOrderItem orderItem, ShowJobResponse showJobResponse) {
        String remark = "";
        if (StringUtils.isNull(showJobResponse)) {
            remark = String.format("jobId为：%s,操作失败: 创建超时, 请联系管理员", jobId);
        } else {
            List<SubJob> subJobs = showJobResponse.getEntities().getSubJobs();
            // 将错误信息拼接
            String failReason = subJobs.stream().map(f -> f.getEntities().getErrorcodeMessage()).collect(Collectors.joining(","));
            remark = String.format("jobId为：%s,操作失败：%s, 请联系管理员", jobId, failReason);
        }

        CnOrder cnOrder = cnOrderService.getById(orderItem.getOrderId());
        cnOrder.setOrderStatus(OrderStatusEnum.BUY_FAIL);
        cnOrder.setRemark(remark);
        cnOrderService.updateById(cnOrder);
        log.error(remark);

        orderItem.setOrderStatus(OrderStatusEnum.BUY_FAIL);
        orderItem.setRemark(remark);
        cnOrderItemService.updateById(orderItem);

        // 如果是钱包支付，退回用户的余额，如果是对公支付，不退回用户的余额
        if (PaymentMethodEnum.WALLET.name().equals(cnOrder.getPaymentMethod())) {
            // 购买失败，退回用户的余额
            cnWalletLogService.updateUserBalanceAndLog(orderItem.getUserId(),
                    orderItem.getUpdatePrice(),
                    PaymentMethodEnum.REFUND.name(), null, orderItem.getShoppingCarEnums(), null, null);
        }
    }

    // 修改价格查询json字符串
    private void updatePriceQueryJsonStr(CnUserCloudServersRelation cloudServersRelation, CnOrderItem orderItem) {
        String priceQueryJsonStr = cloudServersRelation.getPriceQueryJsonStr();
        RateOnPeriodReq rateOnPeriodReq = JSONObject.parseObject(priceQueryJsonStr, RateOnPeriodReq.class);
        List<PeriodProductInfo> periodProductInfos = rateOnPeriodReq.getProductInfos();

        String jsonStr = orderItem.getJsonStr();
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        Integer type = (Integer) jsonObject.get("type");
        int size = periodProductInfos.size() + 1;
        if (type == 1) {
            String flavorRef = jsonObject.getString("flavorRef");
            for (PeriodProductInfo periodProductInfo : periodProductInfos) {
                if (StringUtils.equals("hws.service.type.ec2", periodProductInfo.getCloudServiceType())
                        && StringUtils.equals("hws.resource.type.vm", periodProductInfo.getResourceType())) {
                    periodProductInfo.setResourceSpec(flavorRef + ".linux");
                    break;
                }
            }
        } else if (type == 2) {
            JSONArray disks = jsonObject.getJSONArray("disks");
            for (int i = 0; i < disks.size(); i++) {
                // 获取新增磁盘数组
                JSONObject disk = disks.getJSONObject(i);
                // 封装磁盘查询价格参数
                PeriodProductInfo diskPeriodProductInfo = new PeriodProductInfo();
                int diskPeriodProductInfoId = i + size;
                diskPeriodProductInfo.setId(diskPeriodProductInfoId + "");
                diskPeriodProductInfo.setCloudServiceType("hws.service.type.ebs");
                diskPeriodProductInfo.setResourceType("hws.resource.type.volume");
                diskPeriodProductInfo.setRegion("cn-east-3");
                diskPeriodProductInfo.setAvailableZone("cn-east-3");
                diskPeriodProductInfo.setPeriodType(1);
                diskPeriodProductInfo.setPeriodNum(1);
                diskPeriodProductInfo.setSubscriptionNum(1);
                diskPeriodProductInfo.setResourceSpec(disk.getString("diskType"));
                diskPeriodProductInfo.setResourceSize(disk.getInteger("size"));
                diskPeriodProductInfo.setSizeMeasureId(17);
                periodProductInfos.add(diskPeriodProductInfo);
            }
        } else if (type == 3) {
            // 带宽类型
            String bandwidthType = jsonObject.getString("bandwidthType");
            // 带宽大小
            Integer bandwidthSize = jsonObject.getInteger("bandwidthSize");
            for (PeriodProductInfo periodProductInfo : periodProductInfos) {
                if (StringUtils.equals("hws.service.type.vpc", periodProductInfo.getCloudServiceType())
                        && StringUtils.equals("hws.resource.type.bandwidth", periodProductInfo.getResourceType())) {
                    periodProductInfo.setResourceSpec(bandwidthType);
                    periodProductInfo.setResourceSize(bandwidthSize);
                    break;
                }
            }
        }
        cloudServersRelation.setPriceQueryJsonStr(JSON.toJSONString(rateOnPeriodReq));
    }

    /**
     * 保存用户与服务器之间的关系
     *
     * @param dbCnOrderItem 订单子项
     * @param sn            订单号
     */
    private void saveUserAndServerRelation(CnOrderItem dbCnOrderItem, String sn) {
        CnUserCloudServersRelation cnUserCloudServersRelation = new CnUserCloudServersRelation();
        BeanUtils.copyBeanProp(cnUserCloudServersRelation, dbCnOrderItem);
        // 购买时间
        cnUserCloudServersRelation.setBuyingTime(new Date());
        // 过期时间
        Date expirationTime = DateUtils.calcExpirationTime(dbCnOrderItem.getPeriodType(), dbCnOrderItem.getPeriodNum(), null);
        cnUserCloudServersRelation.setExpirationTime(expirationTime);
        cnUserCloudServersRelation.setStatus(ServerStatusEnum.ACTIVE);
        cnUserCloudServersRelation.setOrderItemId(dbCnOrderItem.getOrderItemId());
        // 保存用户购买的云市场和政务云的服务器
        boolean success = userCloudServersRelationService.save(cnUserCloudServersRelation);
        if (success) {
            // 获取用户信息
            SysUser sysUser = userService.selectUserById(cnUserCloudServersRelation.getUserId());
            // 发送短信
            String msg = String.format("[\"%s\",\"%s\"]", cnUserCloudServersRelation.getShoppingCarEnums().getDescription(), sn);
            SmsDTO smsDTO = new SmsDTO(msg, sysUser.getPhonenumber());
            smsService.sendMsg(smsDTO, SmsTemplateEnum.EXPIRATION_NOTICE);
        }

    }

    /**
     * 查询服务器创建状态
     *
     * @param cnOrderItem
     */
    private void queryAndSaveServerStatus(String paymentMethod, CnOrderItem cnOrderItem) {


        PrePaidServerDTO prePaidServerDTO = JsonUtils.toObject(cnOrderItem.getJsonStr(), PrePaidServerDTO.class);
        prePaidServerDTO.setRegionId(cnOrderItem.getRegionId());

        // 创建服务器
        AjaxResult ajaxResult = cloudServiceService.createServers(prePaidServerDTO);
        if (!ajaxResult.containsKey("data") || Objects.isNull(ajaxResult.get("data")) || (int) ajaxResult.get("code") != 200) {
            throw new ServiceException(ajaxResult.get("msg") + "");
        }
        CreateServersResponse response = (CreateServersResponse) ajaxResult.get("data");
        List<String> serverIds = response.getServerIds();
        log.info("创建服务器返回的数据：{}", response);

        // 查询服务器状态
        long startTime = System.currentTimeMillis();
//         异步线程查询服务器创建状态
        ThreadUtil.execAsync(() -> {
            try {
                // 记录任务状态
                ShowJobResponse.StatusEnum statusEnum = ShowJobResponse.StatusEnum.RUNNING;
                // 执行10分钟
                while ((System.currentTimeMillis() - startTime) < 1000 * 60 * 10) {
                    ShowJobResponse showJobResponse = cloudServiceService.showJob(response.getJobId(), cnOrderItem.getRegionId());
                    if (null == showJobResponse) return;
                    log.info("正在创建服务器: " + showJobResponse.getStatus());
                    statusEnum = showJobResponse.getStatus();
                    if (showJobResponse.getStatus().equals(ShowJobResponse.StatusEnum.SUCCESS)) {
                        ListPayPerUseCustomerResourcesRequest resourcesRequest = new ListPayPerUseCustomerResourcesRequest();
                        QueryResourcesReq body = new QueryResourcesReq();
                        body.setResourceIds(serverIds);
                        body.setOnlyMainResource(1); // 只查询主资源
                        resourcesRequest.setBody(body);

                        ListPayPerUseCustomerResourcesResponse listPayPerUseCustomerResourcesResponse = null;
                        List<OrderInstanceV2> customerResourcesResponseData = new ArrayList<>();
                        for (int i = 0; i < 4; i++) {
                            log.info("开始睡眠~~{}", new Date());
                            Thread.sleep(60 * 1000);

                            log.info("结束睡眠~~{}", new Date());
                            // 查询服务器信息
                            listPayPerUseCustomerResourcesResponse = cloudServiceService.listPayPerUseCustomerResources(resourcesRequest);

                            if (null == listPayPerUseCustomerResourcesResponse) {
                                log.error("查询服务器响应信息失败");
                            }
                            customerResourcesResponseData = listPayPerUseCustomerResourcesResponse.getData();
                            if (CollectionUtils.isEmpty(customerResourcesResponseData)) {
                                log.error("查询服务器信息失败");
                            } else {
                                i = 5;
                            }
                            log.info("查询服务器响应信息---------:{}", listPayPerUseCustomerResourcesResponse.toString());
                        }

                        Map<String, OrderInstanceV2> orderInstanceV2Map = customerResourcesResponseData.stream().collect(Collectors.toMap(OrderInstanceV2::getResourceId, Function.identity()));

                        // 创建成功 保存用户与服务器的关系
                        List<CnUserCloudServersRelation> cnUserCloudServersRelations = new ArrayList<>(serverIds.size());
                        for (String serverId : serverIds) {
                            // 查询服务器信息
                            ListServersDetailsRequestDTO listServersDetailsRequestDTO = new ListServersDetailsRequestDTO();
                            listServersDetailsRequestDTO.setServerId(serverId);
                            ListServersDetailsResponse listServersDetailsResponse = cloudControlService.listServersDetails(listServersDetailsRequestDTO);

                            CnUserCloudServersRelation cnUserCloudServersRelation = new CnUserCloudServersRelation();
                            cnUserCloudServersRelation.setStatus(ServerStatusEnum.ACTIVE);
                            cnUserCloudServersRelation.setId(SnowFlakeUtil.getSnowFlakeId());
                            cnUserCloudServersRelation.setUserId(cnOrderItem.getUserId());
                            cnUserCloudServersRelation.setRelationId(serverId);
                            cnUserCloudServersRelation.setOrderItemId(cnOrderItem.getOrderItemId());
                            cnUserCloudServersRelation.setPriceQueryJsonStr(cnOrderItem.getPriceQueryJsonStr());
                            // 计费模式
                            cnUserCloudServersRelation.setPeriodType(cnOrderItem.getPeriodType());
                            // 保存服务器的购买时间
                            OrderInstanceV2 orderInstanceV2 = orderInstanceV2Map.get(serverId);
                            cnUserCloudServersRelation.setBuyingTime(DateUtils.TZCovertString(orderInstanceV2.getEffectiveTime()));
                            // 保存服务器的过期时间
                            cnUserCloudServersRelation.setExpirationTime(DateUtils.TZCovertString(orderInstanceV2.getExpireTime()));
                            // 0：到期进入宽限期  1：到期转按需 2：到期后自动删除（从生效中直接删除） 3：到期后自动续费 4：到期后冻结 5：到期后删除（从保留期删除）
                            cnUserCloudServersRelation.setAutoRenew(orderInstanceV2.getExpirePolicy() == 3);
                            // 类型
                            cnUserCloudServersRelation.setShoppingCarEnums(ShoppingCarEnums.CLOUD_SERVER);
                            // 保存最终服务器的成交价格
                            cnUserCloudServersRelation.setUpdatePrice(cnOrderItem.getUpdatePrice());
                            cnUserCloudServersRelation.setDiscountPrice(cnOrderItem.getDiscountPrice());
                            cnUserCloudServersRelation.setOriginalPrice(cnOrderItem.getOriginalPrice());
                            cnUserCloudServersRelation.setEbsPrice(cnOrderItem.getEbsPrice());
                            cnUserCloudServersRelation.setEc2Price(cnOrderItem.getEc2Price());
                            cnUserCloudServersRelation.setVpcPrice(cnOrderItem.getVpcPrice());
                            cnUserCloudServersRelation.setOrderAbstract(cnOrderItem.getOrderAbstract());
                            cnUserCloudServersRelation.setJsonStr(JSONObject.toJSONString(listServersDetailsResponse));
                            cnUserCloudServersRelation.setTotalPrice(cnOrderItem.getUpdatePrice());

                            Integer periodType = cnOrderItem.getPeriodType();
                            // 获取总计购买月份
                            if (periodType == 30) {
                                cnUserCloudServersRelation.setMonths(cnOrderItem.getPeriodNum());
                            } else if (periodType == 360) {
                                cnUserCloudServersRelation.setMonths(cnOrderItem.getPeriodNum() * 12);
                            }
                            cnUserCloudServersRelations.add(cnUserCloudServersRelation);
                        }
                        userCloudServersRelationService.saveBatch(cnUserCloudServersRelations);
                        break;
                        // 创建服务器失败，记录失败原因 并退回用户的余额
                    } else if (showJobResponse.getStatus().equals(ShowJobResponse.StatusEnum.FAIL)) {
                        // 将错误信息拼接
                        taskFailed(response.getJobId(), cnOrderItem, showJobResponse);
                        break;
                    }
                    Thread.sleep(1000 * 10);
                }
                if (!statusEnum.equals(ShowJobResponse.StatusEnum.SUCCESS)) {
                    taskFailed(response.getJobId(), cnOrderItem, null);
                }
            } catch (Exception e) {
                log.error("异步查询购买服务器状态失败" + e);
            }
            log.debug("异步查询购买服务器状态结束");
        });
    }


//
//    public static void main(String[] args) {
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        Date expirationTime = calcExpirationTime(365, 1);
//        System.out.println(simpleDateFormat.format(expirationTime));
//    }

}
